﻿package Engine.RMI
{
    import Engine.flash.*;
    import Framework.Holder.*;
    import Framework.MQ.*;
    import Framework.Protocol.*;
    import Framework.Protocol.CDFProtocol.*;
    import Framework.Serialize.*;
    import Framework.Util.*;
    import flash.events.*;
    import flash.net.*;
    import flash.utils.*;

    public class RMIConnection extends EventSender implements IIOHandler, IBusinessHandler
    {
        public var isConnnetClose:Boolean = false;
        private const tencentHead1:String = "tgw_l7_forward";
        private var _socket:Socket;
        private var _protocol:IProtocol;
        private var _session:Session;
        private var _timeOutCount:int;
        private var _timer:Timer;
        private var _delay:int = 10000;
        private var _keepActionBack:AMI_IKeepActive_keepActive;
        private static var isFirst:Boolean = true;
        private static var tencentHead2:String = "Host:s200.app1104852585.twsapp.com:8000";

        public function RMIConnection(param1:IProtocol)
        {
            if (param1 == null)
            {
                this._protocol = new Protocol();
            }
            else
            {
                this._protocol = param1;
            }
            this._socket = new Socket();
            this._socket.addEventListener(IOErrorEvent.IO_ERROR, this.ioErrorHandler);
            this._socket.addEventListener(Event.CONNECT, this.connectHandler);
            this._socket.addEventListener(Event.CLOSE, this.closeHandler);
            this._socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, this.securityErrorHandler);
            this._socket.addEventListener(ProgressEvent.SOCKET_DATA, this.socketDataHandler);
            this._timer = new Timer(this._delay);
            this._timer.addEventListener(TimerEvent.TIMER, this.onTimerHandler);
            this._timeOutCount = 0;
            this._keepActionBack = new AMI_IKeepActive_keepActive();
            return;
        }// end function

        private function onTimerHandler(event:TimerEvent) : void
        {
            if (this._session && this._session.communicator && this._session.communicator.connected)
            {
                var _loc_2:String = this;
                _loc_2._timeOutCount = this._timeOutCount + 1;
                if (++this._timeOutCount == 2)
                {
                    this._session.keepActivePrx.keepActive_async(this._keepActionBack);
                }
            }
            return;
        }// end function

        public function get session() : Session
        {
            return this._session;
        }// end function

        public function set session(param1:Session) : void
        {
            this._session = param1;
            return;
        }// end function

        private function ioErrorHandler(event:IOErrorEvent) : void
        {
            var _loc_2:* = event.text;
            this.close();
            if (this._session.communicator.sessionEvent)
            {
                this._session.communicator.sessionEvent.onAbandon(this._session);
            }
            this.processException(_loc_2, RMIException.ExceptionCodeConnectionWrite);
            return;
        }// end function

        private function connectHandler(event:Event) : void
        {
            var _loc_4:RMIObjectBind = null;
            var _loc_5:Exception = null;
            this._timer.start();
            this._timeOutCount = 0;
            dispatchEvent(new Event(Event.CONNECT));
            this._session.connection = this;
            this._session.communicator.connecting = false;
            this._session.communicator.connected = true;
            var _loc_2:* = new ArrayHolder();
            this._session.pinkMessage(_loc_2);
            var _loc_3:int = 0;
            while (_loc_3 < _loc_2.value.length)
            {
                
                _loc_4 = _loc_2.value[_loc_3] as RMIObjectBind;
                if (_loc_4.outgoingStatus == RMIObjectBind.EOutGoingWaitToSend)
                {
                    if (this.send(_loc_4.buffer.byteArray) == -1)
                    {
                        if (_loc_4.rmiObject)
                        {
                            this._session.removeBackObject(_loc_4.messageId);
                            _loc_5 = new RMIException("RMIConnection:send fail", RMIException.ExceptionCodeConnectionWrite);
                            _loc_4.rmiObject.cdeException(_loc_5);
                        }
                    }
                }
                _loc_3++;
            }
            return;
        }// end function

        private function closeHandler(event:Event) : void
        {
            dispatchEvent(new Event(Event.CLOSE));
            trace("RMIConnection closeHandler");
            this.close();
            if (this._session.communicator.sessionEvent)
            {
                this._session.communicator.sessionEvent.onAbandon(this._session);
            }
            this.processException("Connected Close", RMIException.ExceptionCodeConnectionClosed);
            this._protocol.clear();
            return;
        }// end function

        private function securityErrorHandler(event:SecurityErrorEvent) : void
        {
            trace("RMIConnection:" + event.text);
            var _loc_2:* = this._session.communicator.url + ":" + event.text;
            this._session.connection = null;
            this._session.communicator.connecting = false;
            this._session.communicator.connected = false;
            this.isConnnetClose = true;
            if (this._session.communicator.sessionEvent)
            {
                this._session.communicator.sessionEvent.onAbandon(this._session);
            }
            this.processException(_loc_2, RMIException.ExceptionCodeConnectionNotConnect);
            return;
        }// end function

        private function socketDataHandler(event:ProgressEvent) : void
        {
            var _loc_2:* = getTimer();
            var _loc_3:* = new ByteArray();
            this._socket.readBytes(_loc_3);
            var _loc_4:* = this._protocol.handleData(_loc_3, this, this, null);
            _loc_3.clear();
            if (_loc_4 == -1)
            {
                throw new Error("网络数据处理失败");
            }
            return;
        }// end function

        public function connect(param1:String, param2:int) : void
        {
            this._session.communicator.connecting = true;
            this._socket.connect(param1, param2);
            return;
        }// end function

        public function close() : void
        {
            this._socket.close();
            this._timer.removeEventListener(TimerEvent.TIMER, this.onTimerHandler);
            this._timer.stop();
            this._session.connection = null;
            this._session.communicator.connecting = false;
            this._session.communicator.connected = false;
            this._timeOutCount = 0;
            this.isConnnetClose = true;
            return;
        }// end function

        public function send(param1:ByteArray) : int
        {
            return this._protocol.sendDataEncrypt(param1, this) ? (0) : (-1);
        }// end function

        private function addTencentHead(param1:ByteArray) : ByteArray
        {
            var i:int;
            var inBuf:* = param1;
            var tempBuff:* = new ByteArray();
            tempBuff.position = 0;
            i;
            while (i < this.tencentHead1.length)
            {
                
                tempBuff.writeByte(this.tencentHead1.charCodeAt(i));
                i = (i + 1);
            }
            tempBuff.writeByte(13);
            tempBuff.writeByte(10);
            i;
            while (i < tencentHead2.length)
            {
                
                tempBuff.writeByte(tencentHead2.charCodeAt(i));
                i = (i + 1);
            }
            tempBuff.writeByte(13);
            tempBuff.writeByte(10);
            tempBuff.writeByte(13);
            tempBuff.writeByte(10);
            try
            {
                this._socket.writeBytes(tempBuff, 0, tempBuff.length);
                this._socket.flush();
            }
            catch (ex:Error)
            {
                return inBuf;
            }
            return inBuf;
        }// end function

        public function sendData(param1:ByteArray, param2:int) : int
        {
            var inBuf:* = param1;
            var len:* = param2;
            try
            {
                this._timeOutCount = 0;
                if (isFirst)
                {
                    inBuf = this.addTencentHead(inBuf);
                }
                isFirst = false;
                this._socket.writeBytes(inBuf, 0, len);
                this._socket.flush();
            }
            catch (ex:Error)
            {
                return -1;
            }
            return 0;
        }// end function

        public function handlePacket(param1:ByteArray, param2:IBusinessHandler) : Boolean
        {
            var call:SRMICall;
            var rmiObject:RMIObject;
            var context:Context;
            var outStream:SerializeStream;
            var dispatchStatus:ERMIDispatchStatus;
            var __os:SerializeStream;
            var callRet:SRMIReturn;
            var callRet1:SRMIReturn;
            var rmiObjectBind:RMIObjectBind;
            var context1:Context;
            var mb:MessageBlock;
            var inBuf:* = param1;
            var handler:* = param2;
            var isStream:* = new SerializeStream();
            isStream.byteArray = inBuf;
            var messageType:* = ERMIMessageType.__read(isStream);
            if (messageType.equals(ERMIMessageType.MessageTypeCall))
            {
                call = new SRMICall();
                call.__read(isStream);
                rmiObject = this._session.findObject(call.identity);
                if (rmiObject == null)
                {
                    trace(call.identity.name + " object not find");
                    isStream.dispose();
                    return true;
                }
                context = new Context();
                context._session = this._session;
                context._connection = this;
                context._messageId = call.messageId;
                context._dispachStatus = ERMIDispatchStatus.DispatchOK;
                outStream = new SerializeStream();
                try
                {
                    dispatchStatus = rmiObject.__dispatch(context, call, isStream, outStream);
                }
                catch (ex:Exception)
                {
                    trace(ex.message);
                    outStream.clear();
                    outStream.writeException(ex);
                    dispatchStatus = ERMIDispatchStatus.DispatchException;
                }
                if (call.messageId == 0 || dispatchStatus.equals(ERMIDispatchStatus.DispatchAsync))
                {
                    isStream.dispose();
                    outStream.dispose();
                    return true;
                }
                __os = new SerializeStream();
                ERMIMessageType.MessageTypeCallRet.__write(__os);
                callRet = new SRMIReturn();
                callRet.messageId = call.messageId;
                callRet.dispatchStatus = dispatchStatus;
                callRet.__write(__os);
                __os.writeByteArray(outStream);
                isStream.dispose();
                outStream.dispose();
                return this.send(__os.byteArray) != -1;
            }
            else if (messageType.equals(ERMIMessageType.MessageTypeCallRet))
            {
                callRet1 = new SRMIReturn();
                callRet1.__read(isStream);
                rmiObjectBind = this._session.findRemoveBackObject(callRet1.messageId);
                if (rmiObjectBind == null)
                {
                    trace(callRet1.messageId + " message id not find");
                    isStream.dispose();
                    return true;
                }
                context1 = new Context();
                context1._session = this._session;
                context1._connection = this;
                context1._messageId = callRet1.messageId;
                context1._dispachStatus = callRet1.dispatchStatus;
                rmiObjectBind.__back(context1, isStream);
            }
            else if (messageType.equals(ERMIMessageType.MessageTypeMQ))
            {
                mb = new MessageBlock();
                mb.__read(isStream);
                if (this._session.messageHandler)
                {
                    this._session.messageHandler.onMessage(mb);
                }
            }
            isStream.dispose();
            return true;
        }// end function

        private function processException(param1:String, param2:int) : void
        {
            var _loc_6:RMIObjectBind = null;
            var _loc_3:* = new ArrayHolder();
            this._session.pinkRemoveMessage(_loc_3);
            var _loc_4:* = new Exception(param1, param2);
            var _loc_5:int = 0;
            while (_loc_5 < _loc_3.value.length)
            {
                
                _loc_6 = _loc_3.value[_loc_5] as RMIObjectBind;
                if (_loc_6 != null)
                {
                    if (this._session.communicator.prepareCommandHandler)
                    {
                        this._session.communicator.prepareCommandHandler.prepareBackException(_loc_6.rmiObject, _loc_4);
                    }
                    _loc_6.rmiObject.cdeException(_loc_4);
                }
                _loc_5++;
            }
            return;
        }// end function

        public static function set connetIPPort(param1:String) : void
        {
            tencentHead2 = "Host:" + param1;
            isFirst = true;
            return;
        }// end function

    }
}
